第25天。最近遇到一些事情發展與我預想中不太一樣時,當下挺焦慮的,但事後發現我焦慮的原因竟然不是事件本身的好壞,而是因為”與預想不一樣“。我脆弱的內心: \
最明顯可以讓程式遵守開放-封閉原則的方法,就是找出程式中會發生變化的地方,並且將它封裝起來,把系統中穩定和變化的部分區隔開來。在上半部的範例中,由於動物的叫聲是會變的,因此我們把這部分從makeSound中抽離出來,我們的做法是利用物件的多態性,除了多態性之外,我們還有些方法可以來協助我們更容易達到開放-封閉原則。
第一個方法是‘放置掛鉤(hook)’,掛鉤的做法我們在範本方法模式中有使用過(https://ithelp.ithome.com.tw/articles/10204797),父類別封裝了子類別的眼算法架構,有些較特別的子類別就可以利用hook做個人化的行為。
第二個方法是使用callback function,callback函數可以最為一個參數傳入另一個方法中,我們把具變化的行為封裝在callback函數裡頭,當被執行的時候就會有不同的結果。其實這樣的行為跟hook意義上是有點類似的。
開放-封閉原則其實是‘好程式’都應該達成的目標,我們來回顧一下前面幾種模式如何遵守此原則
發佈-訂閱模式:
把物件之間的關係,利用發送者或是訂閱者的行為來做區分。當有新訂閱者出現時,發佈者完全不需要變動,而發佈者修改內容時,訂閱者也不會受到影響。
範本方法模式:
此模式中,子類別大致的演算法架構是固定的,我們把架構抽出來放在父類別中,子類別則實作演算法內容。當子類別演算法內容如何修改都不會影養到父類別,且通過新增子類別的方式就可以增加新功能,並不會影響其他子類別或是父類別,這樣是符合開放-封閉原則的。
策略模式:
策略模式將方法都封裝成獨立策略類別,使用者可以隨意更換,並且新增或是修改策略類別時,其他物件也不會受到影響。
代理模式:
在我們範例中,我們將功能模組分割為預載入圖片功能與設置元素功能,這兩個模組其實都可以獨立改變互不相影響,每個物件都專注在自己的職責中。
職責鏈模式:
範例中我們把每個互相關聯的方法獨立封裝成各自的類別,當我們有新方法要加入,只要長出新類別,並且加入職責鏈當中就好。
就職責鏈模式來說,加入新的方法其實還是要小幅度的修改職責鏈當中的程式碼,可能會想說這樣也算是修改到原始的程式碼了:
fn1.setNextStage(fn2).setNextStage(fn3);
變成
fn1.setNextStage(fn2).setNextStage(fn2_1).setNextStage(fn3);
其實某些時候並不一定要完全做到不修改原本的程式碼,實際就算技術上做得到,我們可能也會投注過多的時間成本在上面。我們要可慮的應該是:
1.找出最會發生變化的地方,並抽象化來封閉它。
2.若一定會發生修改的狀況,盡可能的修改相對容易的地方。
實際開發時,可能很多時候會假設這些方法是不會有變化的,這樣可以快速開發完成。但是當變化出現時,我們就必須要思考如何不會再讓第二次變化為難我們。